package com.example.extra.request;

import com.example.extra.common.CachedBodyServletInputStream;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StreamUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lixiang
 */
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {


    private final byte[] cachedBody; // 存储缓存体的字节数组
    private final Map<String, String[]> parameterMap;

    // 构造函数
    public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        // 使用Spring的StreamUtils或其他工具将输入流读取到字节数组
        this.cachedBody = StreamUtils.copyToByteArray(request.getInputStream());
        // 如果是 multipart 请求，需要特殊处理参数
        if (isMultipartRequest(request)) {
            this.parameterMap = Collections.unmodifiableMap(new HashMap<>(request.getParameterMap()));
        } else {
            this.parameterMap = Collections.unmodifiableMap(new HashMap<>(request.getParameterMap()));
        }
    }

    // 添加一个公共的getter方法，允许外部获取缓存体的副本
    public byte[] getCachedBody() {
        // 返回副本是一种保护性拷贝，防止外部修改破坏内部数据
        return cachedBody.clone();
    }

    // 重写getInputStream，基于缓存的字节数组返回新的ServletInputStream
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new CachedBodyServletInputStream(this.cachedBody); // 使用缓存的字节数组
    }

    // 重写getReader
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream(), StandardCharsets.UTF_8));
    }

    @Override
    public String getParameter(String name) {
        String[] values = parameterMap.get(name);
        if (values != null && values.length > 0) {
            return values[0];
        }
        return null;
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        return Collections.enumeration(parameterMap.keySet());
    }

    @Override
    public String[] getParameterValues(String name) {
        return parameterMap.get(name);
    }

    private byte[] toByteArray(InputStream inputStream) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int nRead;
        byte[] data = new byte[1024];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        return buffer.toByteArray();
    }

    private boolean isMultipartRequest(HttpServletRequest request) {
        String contentType = request.getContentType();
        return contentType != null && contentType.startsWith("multipart/");
    }


}
